package com.qhyt.generate;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author jie
 * @date 2020/10/21 -15:04
 */
public class GenerateUtils {

    private static final char UNDERLINE = '_';
    private static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");
    private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");

    private static String getDateStr() {
        Date currentTime = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        return format.format(currentTime);
    }

    /**
     * entity
     */
    public static String getEntityStr(String entity, String companyName, List<TableEntity> tableEntityList, boolean guidFlag) {
        String dateStr = getDateStr();

        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".model.").append(getPackagePrefix(entity)).append(";\n").append("\n\n");
        sb.append("import java.util.Date;\n");
        sb.append("import java.math.BigDecimal;\n");
        if (!guidFlag) {
            sb.append("import com." + companyName + ".model.manual.CustomizePrimaryKey;\n");

        } else {
            sb.append("import com." + companyName + ".framework.core.pojo.model.GenericGuidModel;\n");
        }

        sb.append("\n" + "/**\n" + " * (").append(entity).append(")实体类\n").append(" *\n").append(" * @author jie\n").append(" * @date ").append(dateStr).append("\n").append(" */\n").append("public class ").append(entity).append(" extends ");
        if (!guidFlag) {
            sb.append("CustomizePrimaryKey {\n");

        } else {
            sb.append("GenericGuidModel {\n");
        }

        for (TableEntity tableEntity : tableEntityList) {
            String field = tableEntity.getField();
            if (ignoreFields(field)) {
                continue;
            }

            if ("BigDecimal".equals(tableEntity.getType())) {
                sb.append("    private ").append(tableEntity.getType()).append(" ").append(field).append(" = new BigDecimal(0)").append(";\n");
            } else {
                sb.append("    private ").append(tableEntity.getType()).append(" ").append(field).append(";\n");
            }


        }

        sb.append("\n");

        for (TableEntity tableEntity : tableEntityList) {
            String field = tableEntity.getField();
            if (ignoreFields(field)) {
                continue;
            }

            String type = tableEntity.getType();

            sb.append("\tpublic ").append(type).append(" get").append(prefixLetterCap(field)).append("() {\n");
            sb.append("\t\treturn ").append(field).append(";\n");
            sb.append("\t}\n");

            sb.append("\tpublic void ").append("set").append(prefixLetterCap(field)).append("(").append(type).append(" ").append(field).append(") {\n");
            sb.append("\t\tthis.").append(field).append(" = ").append(field).append(";\n");
            sb.append("\t}\n\n");
        }

        if (!guidFlag) {
            sb.append("\n" +
                    "    @Override\n" +
                    "    public String getNameCn() {\n" +
                    "        return null;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public String getNameEn() {\n" +
                    "        return null;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public String getNameTc() {\n" +
                    "        return null;\n" +
                    "    }");
        }

        sb.append("\n}");

        return sb.toString();
    }

    private static boolean ignoreFields(String field) {
        return "id".equalsIgnoreCase(field) ||
                "insertTime".equalsIgnoreCase(field) ||
                "insertUser".equalsIgnoreCase(field) ||
                "updateTime".equalsIgnoreCase(field) ||
                "updateUser".equalsIgnoreCase(field) ||
                "deleteFlag".equalsIgnoreCase(field) ||
                field.startsWith("attr");
    }

    /**
     * mapper
     */
    public static String getMapperStr(String entity, String companyName) {
        String dateStr = getDateStr();
        return "package com." + companyName + ".mapper." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com." + companyName + ".framework.dao.GenericMapper;\n" +
                "import com." + companyName + ".model." + getPackagePrefix(entity) + "." + entity + ";\n" +
                "import org.apache.ibatis.annotations.Mapper;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "@Mapper\n" +
                "public interface " + entity + "Mapper extends GenericMapper<" + entity + "> {\n" +
                "}\n";
    }


    /**
     * dao
     */
    public static String getDaoStr(String entity, String companyName, boolean guidFlag, String pkPrefix, Field[] fields, List<Parameters> parametersList) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".dao." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "PageDto;\n" +
                "import com." + companyName + ".framework.dao.GenericDao;\n" +
                "import com." + companyName + ".mapper." + getPackagePrefix(entity) + "." + entity + "Mapper;\n" +
                "import com." + companyName + ".model." + getPackagePrefix(entity) + "." + entity + ";\n" +
                "import com.github.pagehelper.PageInfo;\n" +
                "import com." + companyName + ".dao.MultipartTable;\n" +
                "import com." + companyName + ".dao.TableInfo;\n" +
                "import org.apache.commons.lang3.StringUtils;\n" +
                "import com." + companyName + ".vo." + getPackagePrefix(entity) + "." + entity + "PageVo;\n" +
                "import com." + companyName + ".framework.dao.serialnumber.SerialNumberGeneratorDao;\n" +
                "import org.apache.ibatis.session.RowBounds;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.stereotype.Repository;\n" +
                "import tk.mybatis.mapper.entity.Example;\n" +
                "\n" +
                "import java.util.List;\n" +
                "import java.util.ArrayList;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "@Repository\n");
        if (!guidFlag) {
            sb.append("public class " + entity + "Dao extends SerialNumberGeneratorDao<" + entity + ", String> {\n");

        } else {
            sb.append("public class " + entity + "Dao extends GenericDao<" + entity + ", String> {\n");
        }

        sb.append("    private " + entity + "Mapper " + prefixLetterLower(entity) + "Mapper;\n" +
                "\n" +
                "    public " + entity + "Dao(@Autowired " + entity + "Mapper " + prefixLetterLower(entity) + "Mapper) {\n" +
                "        super(" + prefixLetterLower(entity) + "Mapper);\n" +
                "        this." + prefixLetterLower(entity) + "Mapper = " + prefixLetterLower(entity) + "Mapper;\n" +
                "    }\n" +
                "\n");

        if (!guidFlag) {
            sb.append("\tpublic String generateId() {\n" +
                    "        Example example = new Example(" + entity + ".class);\n" +
                    "        return generateNewSerialNumer(example, \"" + pkPrefix + "\");\n" +
                    "    }\n\n");

        }

        sb.append("\tpublic PageInfo<" + entity + "PageVo> selectForPage(" + entity + "PageDto " + prefixLetterLower(entity) + "PageDto) {\n" +
                "       MultipartTable multipartTable = new MultipartTable();\n" +
                "\n" +
                "        List<Class> tableNameList = new ArrayList<>();\n" +
                "        tableNameList.add(" + entity + ".class);\n" +
                "        tableNameList.add(" + entity + "Details.class);\n" +
                "\n" +
                "        List<String> tableRelationList = new ArrayList<>();\n" +
                "        tableRelationList.add(\"  t1.id = t2." + prefixLetterLower(entity) + "_id \");\n" +
                "\n" +
                "        List<String> relationTableFieldList = new ArrayList<>();\n" +
                "        relationTableFieldList.add(\"t2.logistics_number\");\n" +
                "\n");

        if (null != fields) {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                String fieldName = field.getName();
                Parameters parameters = parametersList.get(i);
                String type = parameters.getType();

                if ("select".equals(type) || "search".equals(type)) {
                    sb.append("        multipartTable.andCondition(\"t1." + humpToUnderline(fieldName) + "\", \"=\", " + prefixLetterLower(entity) + "PageDto.get" + prefixLetterCap(fieldName) + "());\n");

                } else if (fieldName.endsWith("From")) {
                    sb.append("        multipartTable.andCondition(\"t1.insert_time\", \">=\", " + prefixLetterLower(entity) + "PageDto.get" + prefixLetterCap(fieldName) + "());\n");

                } else if (fieldName.endsWith("To")) {
                    sb.append("        multipartTable.andCondition(\"t1.insert_time\", \"<=\", " + prefixLetterLower(entity) + "PageDto.get" + prefixLetterCap(fieldName) + "());\n");

                } else {
                    sb.append("        multipartTable.andCondition(\"t1." + humpToUnderline(fieldName) + "\", \"like\", " + prefixLetterLower(entity) + "PageDto.get" + prefixLetterCap(fieldName) + "());\n");
                }


            }
        }
        sb.append("\n" +
                "        TableInfo tableInfo = new TableInfo(tableNameList, tableRelationList, relationTableFieldList);\n" +
                "        tableInfo.setPageIndex(" + prefixLetterLower(entity) + "PageDto.getPageIndex());\n" +
                "        tableInfo.setPageSize(" + prefixLetterLower(entity) + "PageDto.getPageSize());\n" +
                "\n" +
                "        List<?> list = multipartTable.multipartTableSearchNoDelete(" + entity + "PageVo.class, tableInfo, null);\n" +
                "\n" +
                "        long count = multipartTable.getCount(tableInfo);\n" +
                "\n" +
                "        PageInfo<" + entity + "PageVo> pageInfo = new PageInfo<>();\n" +
                "        pageInfo.setList((List<" + entity + "PageVo>) list);\n" +
                "        pageInfo.setTotal(count);\n" +
                "        return pageInfo;\n" +
                "    }\n}");

        return sb.toString();
    }

    /**
     * service
     */
    public static String getServiceStr(String entity, String companyName, boolean detailsFlag) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();

        sb.append("package com." + companyName + ".service." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "AddOrUpdateDto;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "PageDto;\n" +
                "import com." + companyName + ".framework.core.pojo.DataTableResponse;\n" +
                "import com." + companyName + ".vo.AddOrUpdateVo;\n" +
                "import com." + companyName + ".vo." + getPackagePrefix(entity) + "." + entity + "PageVo;\n" +
                "\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public interface " + entity + "Service {\n" +
                "    DataTableResponse<List<" + entity + "PageVo>> page(" + entity + "PageDto " + prefixLetterLower(entity) + "PageDto);\n" +
                "    AddOrUpdateVo add(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto);\n" +
                "    AddOrUpdateVo update(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto);\n" +
                "    Integer batchDelete(List<String> ids);\n");
        if (detailsFlag) {
            sb.append("    " + entity + "DetailsVo details(String id);\n");
        }

        sb.append("}");
        return sb.toString();
    }

    /**
     * serviceImpl
     */
    public static String getServiceImplStr(String entity, String companyName, List<Parameters> parametersList, boolean guidFlag) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();

        sb.append("package com." + companyName + ".service." + getPackagePrefix(entity) + ".impl;\n" +
                "\n" +
                "import com.github.pagehelper.PageHelper;\n" +
                "import com.github.pagehelper.PageInfo;\n" +
                "import com." + companyName + ".dao." + getPackagePrefix(entity) + "." + entity + "Dao;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "AddOrUpdateDto;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "PageDto;\n" +
                "import com." + companyName + ".exception.sys_login.InternationalErrorCode;\n" +
                "import com." + companyName + ".framework.core.pojo.DataTableResponse;\n" +
                "import com." + companyName + ".framework.util.BeanUtils;\n" +
                "import com." + companyName + ".model." + getPackagePrefix(entity) + "." + entity + ";\n" +
                "import com." + companyName + ".service." + getPackagePrefix(entity) + "." + entity + "Service;\n" +
                "import com." + companyName + ".vo.AddOrUpdateVo;\n" +
                "import com." + companyName + ".vo." + getPackagePrefix(entity) + "." + entity + "PageVo;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "import org.springframework.transaction.annotation.Transactional;\n" +
                "\n" +
                "import java.util.ArrayList;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "@Service\n" +
                "public class " + entity + "ServiceImpl implements " + entity + "Service {\n" +
                "\n" +
                "    @Autowired\n" +
                "    private " + entity + "Dao " + prefixLetterLower(entity) + "Dao;\n" +
                "\n" +
                "\n");
        sb.append(" @Override\n" +
                "    public DataTableResponse<List<" + entity + "PageVo>> page(" + entity + "PageDto " + prefixLetterLower(entity) + "PageDto) {\n" +
                "\n" +
                "        DataTableResponse<List<" + entity + "PageVo>> dataTableResponse = new DataTableResponse<>();\n" +
                "\n" +
                "        PageInfo<" + entity + "PageVo> pageInfo = " + prefixLetterLower(entity) + "Dao.selectForPage(" + prefixLetterLower(entity) + "PageDto);\n" +
                "        dataTableResponse.setData(pageInfo.getList());\n" +
                "        dataTableResponse.setReturnTotalItems(pageInfo.getTotal());\n" +
                "        return dataTableResponse;\n" +
                "    }");
        sb.append(
                "\n" +
                        "\n" +
                        "    @Override\n" +
                        "    public AddOrUpdateVo add(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                        "        AddOrUpdateVo addOrUpdateVo = new AddOrUpdateVo();\n" +
                        "        " + entity + " " + prefixLetterLower(entity) + " = new " + entity + "();\n" +
                        "\n");
        if (!guidFlag) {
            sb.append("        " + prefixLetterLower(entity) + ".setManualPrimaryKey(" + prefixLetterLower(entity) + "Dao.generateId());\n");
        }

        for (Parameters voParameters : parametersList) {
            sb.append("\t\t").append(prefixLetterLower(entity)).append(".set").append(prefixLetterCap(voParameters.getKey())).append("(").append(prefixLetterLower(entity)).append("AddOrUpdateDto.get").append(prefixLetterCap(voParameters.getKey())).append("());\n");

        }

        sb.append(
                "        " + prefixLetterLower(entity) + "Dao.insertSelective(" + prefixLetterLower(entity) + ");\n" +
                        "        addOrUpdateVo.setId(" + prefixLetterLower(entity) + ".getId());\n" +
                        "        return addOrUpdateVo;\n" +
                        "\n" +
                        "    }\n" +
                        "\n" +
                        "\n" +
                        "    @Override\n" +
                        "    public AddOrUpdateVo update(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                        "        "+entity+" "+prefixLetterLower(entity)+" = checkUpdate("+prefixLetterLower(entity)+"AddOrUpdateDto.getId());\n" +
                        "\n" +
                        "        AddOrUpdateVo addOrUpdateVo = new AddOrUpdateVo();\n" +
                        "//     这里也可以使用copyPropertiesSelective   BeanUtils.copyPropertiesSelective("+prefixLetterLower(entity)+"AddOrUpdateDto, "+prefixLetterLower(entity)+");");

        for (Parameters voParameters : parametersList) {
            if ("id".equals(voParameters.getKey())){
                continue;
            }
            sb.append("\t\t").append(prefixLetterLower(entity)).append(".set").append(prefixLetterCap(voParameters.getKey())).append("(").append(prefixLetterLower(entity)).append("AddOrUpdateDto.get").append(prefixLetterCap(voParameters.getKey())).append("());\n");

        }
        sb.append(
                "\n" +
                        "\n" +
                        "        " + prefixLetterLower(entity) + "Dao.updateByPrimaryKey(" + prefixLetterLower(entity) + ");\n" +
                        "        return addOrUpdateVo;\n" +
                        "\n" +
                        "    }\n" +
                        "\n" +
                        "    private "+entity+" checkUpdate(String id) {\n" +
                        "        " + entity + " " + prefixLetterLower(entity) + " = " + prefixLetterLower(entity) + "Dao.selectByPrimaryKeyNoDelete(id);\n" +
                        "        if (null == " + prefixLetterLower(entity) + ") {\n" +
                        "            throw new RuntimeException(InternationalErrorCode." + getException(entity) + "_NOT_FOUND.getInternationalMessage());\n" +
                        "        }\n" +
                        "        return "+prefixLetterLower(entity)+";" +
                        "    }\n" +
                        "\n" +
                        "    @Transactional(rollbackFor = Exception.class)\n" +
                        "    @Override\n" +
                        "    public Integer batchDelete(List<String> ids) {\n" +
                        "\n" +
                        "        int result = 0;\n" +
                        "\n" +
                        "        List<" + entity + "> " + prefixLetterLower(entity) + "List = " + prefixLetterLower(entity) + "Dao.selectByIds(ids);\n" +
                        "        for (" + entity + " " + prefixLetterLower(entity) + " : " + prefixLetterLower(entity) + "List) {\n" +
                        "            " + prefixLetterLower(entity) + "Dao.delete(" + prefixLetterLower(entity) + ", true);\n" +
                        "            result++;\n" +
                        "        }\n" +
                        "\n" +
                        "        return result;\n" +
                        "    }\n" +
                        "\n" +
                        "}"
        );
        return sb.toString();
    }

    /**
     * serviceImpl2
     */
    public static String getServiceImplStr2(String entity, String companyName, List<Parameters> parametersList, boolean guidFlag) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();

        sb.append("package com." + companyName + ".service." + getPackagePrefix(entity) + ".impl;\n" +
                "\n" +
                "import com.github.pagehelper.PageHelper;\n" +
                "import com.github.pagehelper.PageInfo;\n" +
                "import org.apache.commons.lang3.StringUtils;\n" +
                "import com." + companyName + ".utils.StringConvertUtils;\n" +
                "import com." + companyName + ".utils.CollectionUtils;\n" +
                "import com." + companyName + ".dao." + getPackagePrefix(entity) + "." + entity + "Dao;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "AddOrUpdateDto;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "PageDto;\n" +
                "import com." + companyName + ".exception.sys_login.InternationalErrorCode;\n" +
                "import com." + companyName + ".framework.core.pojo.DataTableResponse;\n" +
                "import com." + companyName + ".framework.util.BeanUtils;\n" +
                "import com." + companyName + ".model." + getPackagePrefix(entity) + "." + entity + ";\n" +
                "import com." + companyName + ".service." + getPackagePrefix(entity) + "." + entity + "Service;\n" +
                "import com." + companyName + ".vo.AddOrUpdateVo;\n" +
                "import com." + companyName + ".vo." + getPackagePrefix(entity) + "." + entity + "PageVo;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "import org.springframework.transaction.annotation.Transactional;\n" +
                "\n" +
                "import java.util.ArrayList;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "@Service\n" +
                "public class " + entity + "ServiceImpl implements " + entity + "Service {\n" +
                "\n" +
                "    @Autowired\n" +
                "    private " + entity + "Dao " + prefixLetterLower(entity) + "Dao;\n" +
                "    @Autowired\n" +
                "    private StringConvertUtils stringConvertUtils;" +
                "\n" +
                "\n");

        // page
        sb.append("\t\t@Override\n" +
                "    public DataTableResponse<List<" + entity + "PageVo>> page(" + entity + "PageDto " + prefixLetterLower(entity) + "PageDto) {\n" +
                "\n" +
                "        DataTableResponse<List<" + entity + "PageVo>> dataTableResponse = new DataTableResponse<>();\n" +
                "\n" +
                "        PageInfo<" + entity + "PageVo> pageInfo = " + prefixLetterLower(entity) + "Dao.selectForPage(" + prefixLetterLower(entity) + "PageDto);\n" +
                "        dataTableResponse.setData(pageInfo.getList());\n" +
                "        dataTableResponse.setReturnTotalItems(pageInfo.getTotal());\n" +
                "        return dataTableResponse;\n" +
                "    }\n\n");

        // add
        sb.append("\t@Transactional\n" +
                "    @Override\n" +
                "    public AddOrUpdateVo add(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        AddOrUpdateVo addOrUpdateVo = new AddOrUpdateVo();\n" +
                "\n" +
                "        String id = add" + entity + "(" + prefixLetterLower(entity) + "AddOrUpdateDto);\n" +
                "        add" + entity + "Details(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + entity + "Details(), id);\n" +
                "\n" +
                "        addOrUpdateVo.setId(id);\n" +
                "        return addOrUpdateVo;\n" +
                "\n" +
                "    }\n");

        sb.append("\tprivate String add" + entity + "(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n");
        boolean addCheckFlag = false;
        for (Parameters voParameters : parametersList) {
            String key = voParameters.getKey();
            if ("warehouseId".equals(key) || "warehouseId".equals(key)) {
                sb.append("        addCheck(" + prefixLetterLower(entity) + "AddOrUpdateDto);\n");
                addCheckFlag = true;
                break;
            }
        }

        sb.append("        " + entity + " " + prefixLetterLower(entity) + " = new " + entity + "();\n" +
                "        BeanUtils.copyProperties(" + prefixLetterLower(entity) + "AddOrUpdateDto, " + prefixLetterLower(entity) + ");\n");
        if (!guidFlag) {
            sb.append("        " + prefixLetterLower(entity) + ".setManualPrimaryKey(" + prefixLetterLower(entity) + "Dao.generateId());\n");
        }

        for (Parameters voParameters : parametersList) {

            String key = voParameters.getKey();
            String type = voParameters.getType();

            if ("list".equals(type) && key.endsWith("Address")) {
                sb.append("        AreaBo areaBo = areaUtils.getAreaBo(" + prefixLetterLower(entity) + "AddOrUpdateDto.getReceiverAddress());\n" +
                        "        if (null != receiverAddressAreaBo) {\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverCountry(areaBo.getCountry());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverProvince(areaBo.getProvince());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverCity(areaBo.getCity());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverDistrict(areaBo.getDistrict());\n" +
                        "        }\n");
                continue;
            }

            if ("list".equals(type)) {
                sb.append("        " + prefixLetterLower(entity) + ".set" + prefixLetterCap(key) + "(stringConvertUtils.list2String(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + prefixLetterCap(key) + "()));\n");
                continue;
            }

            if (key.toLowerCase().endsWith("status")) {
                sb.append("        " + prefixLetterLower(entity) + ".set" + entity + "(" + entity + "Enum.CREATE.getCode());");
                continue;
            }


            if (key.toLowerCase().endsWith("type")) {
                sb.append("        " + prefixLetterLower(entity) + ".set" + entity + "(" + entity + "Enum.Type.getCode());");
            }

        }

        sb.append("        " + prefixLetterLower(entity) + "Dao.insertSelective(" + prefixLetterLower(entity) + ");\n" +
                "        return " + prefixLetterLower(entity) + ".getId();\n" +
                "\n" +
                "    }\n");

        if (addCheckFlag) {
            sb.append("\tprivate void addCheck(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                    "        // 判断仓库和客户是否存在\n" +
                    "        String customerId = " + prefixLetterLower(entity) + "AddOrUpdateDto.getCustomerId();\n" +
                    "        String warehouseId = " + prefixLetterLower(entity) + "AddOrUpdateDto.getWarehouseId();\n" +
                    "        if (StringUtils.isNotEmpty(customerId)) {\n" +
                    "            BasCustomer basCustomer = basCustomerDao.selectByPrimaryKey(customerId);\n" +
                    "            if (basCustomer == null) {\n" +
                    "                throw new RuntimeException(InternationalErrorCode.CUSTOMER_NOT_FOUND.getInternationalMessage());\n" +
                    "            }\n" +
                    "        }\n" +
                    "\n" +
                    "        if (StringUtils.isNotEmpty(warehouseId)) {\n" +
                    "            BasWarehouse basWarehouse = basWarehouseDao.selectByPrimaryKey(warehouseId);\n" +
                    "            if (basWarehouse == null) {\n" +
                    "                throw new RuntimeException(InternationalErrorCode.WAREHOUSE_NOT_FOUND.getInternationalMessage());\n" +
                    "            }\n" +
                    "        }\n" +
                    "    }\n");
        }
        // addDetails
        sb.append("\tprivate void add" + entity + "Details(List<" + entity + "AddOrUpdateDto." + entity + "Details> " + prefixLetterLower(entity) + "DetailsDtoList, String headerId) {\n" +
                "\n" +
                "        List<" + entity + "Details> " + prefixLetterLower(entity) + "DetailsList = " + prefixLetterLower(entity) + "DetailsDao.getBy" + entity + "Id(headerId);\n" +
                "        for (" + entity + "Details " + prefixLetterLower(entity) + "Detail : " + prefixLetterLower(entity) + "DetailsList) {\n" +
                "            " + prefixLetterLower(entity) + "DetailsDao.delete(" + prefixLetterLower(entity) + "Detail, true);\n" +
                "        }\n" +
                "\n" +
                "        for (" + entity + "AddOrUpdateDto." + entity + "Details " + prefixLetterLower(entity) + "DetailsDto : " + prefixLetterLower(entity) + "DetailsDtoList) {\n" +
                "            " + entity + "Details " + prefixLetterLower(entity) + "Details = new " + entity + "Details();\n" +
                "            BeanUtils.copyProperties(" + prefixLetterLower(entity) + "DetailsDto, " + prefixLetterLower(entity) + "Details);\n" +
                "            " + prefixLetterLower(entity) + "Details.set" + entity + "Id(headerId);\n" +
                "            " + prefixLetterLower(entity) + "DetailsDao.insertSelective(" + prefixLetterLower(entity) + "Details);\n" +
                "        }\n" +
                "    }\n");

        // update
        sb.append("\t@Transactional\n" +
                "    @Override\n" +
                "    public AddOrUpdateVo update(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        checkUpdate(" + prefixLetterLower(entity) + "AddOrUpdateDto);\n" +
                "\n" +
                "        AddOrUpdateVo addOrUpdateVo = new AddOrUpdateVo();\n" +
                "\n" +
                "        update" + entity + "(" + prefixLetterLower(entity) + "AddOrUpdateDto);\n" +
                "        add" + entity + "Details(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + entity + "Details(), " + prefixLetterLower(entity) + "AddOrUpdateDto.getId());\n" +
                "\n" +
                "        addOrUpdateVo.setId(" + prefixLetterLower(entity) + "AddOrUpdateDto.getId());\n" +
                "\n" +
                "        return addOrUpdateVo;\n" +
                "\n" +
                "    }\n");

        sb.append("\tprivate void update" + entity + "(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        " + entity + " " + prefixLetterLower(entity) + " = new " + entity + "();\n" +
                "        BeanUtils.copyProperties(" + prefixLetterLower(entity) + "AddOrUpdateDto, " + prefixLetterLower(entity) + ");\n" +
                "        " + prefixLetterLower(entity) + ".setId(" + prefixLetterLower(entity) + "AddOrUpdateDto.getId());\n" +
                "\n");
        for (Parameters voParameters : parametersList) {

            String key = voParameters.getKey();
            String type = voParameters.getType();

            if ("list".equals(type) && key.endsWith("Address")) {
                sb.append("        AreaBo areaBo = areaUtils.getAreaBo(" + prefixLetterLower(entity) + "AddOrUpdateDto.getReceiverAddress());\n" +
                        "        if (null != receiverAddressAreaBo) {\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverCountry(areaBo.getCountry());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverProvince(areaBo.getProvince());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverCity(areaBo.getCity());\n" +
                        "            " + prefixLetterLower(entity) + ".setReceiverDistrict(areaBo.getDistrict());\n" +
                        "        }\n");
                continue;
            }

            if ("list".equals(type)) {
                sb.append("        " + prefixLetterLower(entity) + ".set" + prefixLetterCap(key) + "(stringConvertUtils.list2String(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + prefixLetterCap(key) + "()));\n");
                continue;
            }

        }
        sb.append("        " + prefixLetterLower(entity) + "Dao.updateByPrimaryKeySelective(" + prefixLetterLower(entity) + ");\n" +
                "    }\n");

        sb.append("    private void checkUpdate(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        " + entity + " " + prefixLetterLower(entity) + " = " + prefixLetterLower(entity) + "Dao.selectByPrimaryKeyNoDelete(" + prefixLetterLower(entity) + "AddOrUpdateDto.getId());\n" +
                "        if (null == " + prefixLetterLower(entity) + ") {\n" +
                "            throw new RuntimeException(InternationalErrorCode." + underlineToHump(entity).toUpperCase() + "_NOT_FOUND.getInternationalMessage());\n" +
                "        }\n" +
                "\n" +
                "        if (!" + entity + "StatusEnum.CREATE.getCode().equals(" + prefixLetterLower(entity) + ".get" + entity + "Status())) {\n" +
                "            throw new RuntimeException(InternationalErrorCode.CAN_NOT_MODIFY.getInternationalMessage());\n" +
                "        }\n" +
                "    }\n");

        // details
        sb.append("\t@Override\n" +
                "    public " + entity + "DetailsVo details(String id) {\n" +
                "        " + entity + "DetailsVo " + prefixLetterLower(entity) + "DetailsVo = getHeader(id);\n" +
                "        " + prefixLetterLower(entity) + "DetailsVo.set" + entity + "Details(getDetails(" + prefixLetterLower(entity) + "DetailsVo.getId()));\n" +
                "        return " + prefixLetterLower(entity) + "DetailsVo;\n" +
                "    }\n\n");

        // details Header
        sb.append("\tprivate " + entity + "DetailsVo getHeader(String id) {\n" +
                "\n" +
                "        " + entity + " " + prefixLetterLower(entity) + " = " + prefixLetterLower(entity) + "Dao.selectByPrimaryKeyNoDelete(id);\n" +
                "        if (null == " + prefixLetterLower(entity) + ") {\n" +
                "            throw new RuntimeException(InternationalErrorCode." + entity.toUpperCase() + "_NOT_EXIST.getInternationalMessage());\n" +
                "        }\n" +
                "\n");

        sb.append(
                "        " + entity + "DetailsVo " + prefixLetterLower(entity) + "DetailsVo = new " + entity + "DetailsVo();\n" +
                        "        BeanUtils.copyProperties(" + prefixLetterLower(entity) + ", " + prefixLetterLower(entity) + "DetailsVo);\n" +
                        "        " + prefixLetterLower(entity) + "DetailsVo.setId(" + prefixLetterLower(entity) + ".getId());\n");

        for (Parameters voParameters : parametersList) {

            String key = voParameters.getKey();
            String type = voParameters.getType();

            if ("list".equals(type) && key.endsWith("Address")) {
                sb.append("        String deliveryCountry = " + prefixLetterLower(entity) + ".getDeliveryCountry();\n" +
                        "        String deliveryProvince = " + prefixLetterLower(entity) + ".getDeliveryProvince();\n" +
                        "        String deliveryCity = " + prefixLetterLower(entity) + ".getDeliveryCity();\n" +
                        "        String deliveryDistrict = " + prefixLetterLower(entity) + ".getDeliveryDistrict();\n" +
                        "        String receiverCountry = " + prefixLetterLower(entity) + ".getReceiverCountry();\n" +
                        "        String receiverProvince = " + prefixLetterLower(entity) + ".getReceiverProvince();\n" +
                        "        String receiverCity = " + prefixLetterLower(entity) + ".getReceiverCity();\n" +
                        "        String receiverDistrict = " + prefixLetterLower(entity) + ".getReceiverDistrict();\n");

                sb.append("        " + prefixLetterLower(entity) + "DetailsVo.setDeliveryAddress(areaUtils.getList(deliveryCountry, deliveryProvince, deliveryCity, deliveryDistrict));\n" +
                        "        " + prefixLetterLower(entity) + "DetailsVo.setReceiverAddress(areaUtils.getList(receiverCountry, receiverProvince, receiverCity, receiverDistrict));\n");
                continue;
            }

            if ("list".equals(type)) {
                sb.append("        " + prefixLetterLower(entity) + ".set" + prefixLetterCap(key) + "(stringConvertUtils.list2String(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + prefixLetterCap(key) + "()));\n");
                continue;
            }

        }
        sb.append("        return " + prefixLetterLower(entity) + "DetailsVo;\n" +
                "    }\n");

        // details detail
        sb.append("    private List<" + entity + "DetailsVo." + entity + "Details> getDetails(String headerId) {\n" +
                "        List<" + entity + "DetailsVo." + entity + "Details> " + prefixLetterLower(entity) + "DetailsVoList = new ArrayList<>();\n" +
                "        List<" + entity + "Details> " + prefixLetterLower(entity) + "DetailsList = " + prefixLetterLower(entity) + "DetailsDao.getBy" + entity + "Id(headerId);\n" +
                "        if (CollectionUtils.isEmpty(" + prefixLetterLower(entity) + "DetailsList)) {\n" +
                "            return new ArrayList<>();\n" +
                "        }\n" +
                "\n" +
                "        for (" + entity + "Details " + prefixLetterLower(entity) + "Details : " + prefixLetterLower(entity) + "DetailsList) {\n" +
                "            " + entity + "DetailsVo." + entity + "Details " + prefixLetterLower(entity) + "DetailsVo = new " + entity + "DetailsVo." + entity + "Details();\n" +
                "            BeanUtils.copyProperties(" + prefixLetterLower(entity) + "Details, " + prefixLetterLower(entity) + "DetailsVo);\n" +
                "            " + prefixLetterLower(entity) + "DetailsVoList.add(" + prefixLetterLower(entity) + "DetailsVo);\n" +
                "        }\n" +
                "        return " + prefixLetterLower(entity) + "DetailsVoList;\n" +
                "    }\n");
        // delete
        sb.append("    @Transactional(rollbackFor = Exception.class)\n" +
                "    @Override\n" +
                "    public Integer batchDelete(List<String> ids) {\n" +
                "\n" +
                "        int result = 0;\n" +
                "\n" +
                "        List<" + entity + "> " + prefixLetterLower(entity) + "List = " + prefixLetterLower(entity) + "Dao.selectByIds(ids);\n" +
                "        for (" + entity + " " + prefixLetterLower(entity) + " : " + prefixLetterLower(entity) + "List) {\n" +
                "            " + prefixLetterLower(entity) + "Dao.delete(" + prefixLetterLower(entity) + ", true);\n" +
                "            result++;\n" +
                "        }\n" +
                "\n" +
                "        return result;\n" +
                "    }\n" +
                "\n");
        sb.append("\t}");
        return sb.toString();
    }

    /**
     * controller
     */
    public static String getControllerStr(String entity, String companyName, String description, boolean detailsFlag) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".controller." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "AddOrUpdateDto;\n" +
                "import com." + companyName + ".dto." + getPackagePrefix(entity) + "." + entity + "PageDto;\n" +
                "import com." + companyName + ".framework.core.pojo.DataTableResponse;\n" +
                "import com." + companyName + ".framework.core.pojo.RestfulApiResponse;\n" +
                "import com." + companyName + ".framework.util.annotation.TrimString;\n" +
                "import com." + companyName + ".service." + getPackagePrefix(entity) + "." + entity + "Service;\n" +
                "import com." + companyName + ".vo.AddOrUpdateVo;\n" +
                "import com." + companyName + ".vo." + getPackagePrefix(entity) + "." + entity + "PageVo;\n" +
                "import io.swagger.annotations.Api;\n" +
                "import io.swagger.annotations.ApiOperation;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.validation.BindingResult;\n" +
                "import org.springframework.web.bind.annotation.RequestBody;\n" +
                "import org.springframework.web.bind.annotation.RequestMapping;\n" +
                "import org.springframework.web.bind.annotation.RequestMethod;\n" +
                "import org.springframework.web.bind.annotation.RestController;\n" +
                "\n" +
                "import javax.validation.Valid;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "@RestController\n" +
                "@RequestMapping(path = \"" + getPath(entity) + "\")\n" +
                "@Api(description = \"" + description + "\")\n" +
                "public class " + entity + "Controller {\n" +
                "\n" +
                "    @Autowired\n" +
                "    private " + entity + "Service " + prefixLetterLower(entity) + "Service;\n" +
                "\n" +
                "    @TrimString\n" +
                "    @ApiOperation(\"主页面分页\")\n" +
                "    @RequestMapping(path = \"page\", method = RequestMethod.POST)\n" +
                "    public RestfulApiResponse<DataTableResponse<List<" + entity + "PageVo>>> page(@RequestBody " + entity + "PageDto " + prefixLetterLower(entity) + "PageDto) {\n" +
                "        return RestfulApiResponse.success(\"success\", " + prefixLetterLower(entity) + "Service.page(" + prefixLetterLower(entity) + "PageDto));\n" +
                "    }\n" +
                "\n" +
                "    @TrimString\n" +
                "    @ApiOperation(\"新增\")\n" +
                "    @RequestMapping(path = \"add\", method = RequestMethod.POST)\n" +
                "    public RestfulApiResponse<AddOrUpdateVo> add(@RequestBody @Valid " + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto, BindingResult bindingResult) {\n" +
                "\n" +
                "        if (bindingResult.hasErrors()) {\n" +
                "            return RestfulApiResponse.failure(\"400\", bindingResult.getFieldError().getDefaultMessage());\n" +
                "        }\n" +
                "\n" +
                "        return RestfulApiResponse.success(\"success\", " + prefixLetterLower(entity) + "Service.add(" + prefixLetterLower(entity) + "AddOrUpdateDto));\n" +
                "    }\n" +
                "\n" +
                "    @TrimString\n" +
                "    @ApiOperation(\"修改\")\n" +
                "    @RequestMapping(path = \"update\", method = RequestMethod.POST)\n" +
                "    public RestfulApiResponse<AddOrUpdateVo> update(@RequestBody " + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        return RestfulApiResponse.success(\"success\", " + prefixLetterLower(entity) + "Service.update(" + prefixLetterLower(entity) + "AddOrUpdateDto));\n" +
                "    }\n" +
                "\n");

        if (detailsFlag) {
            sb.append("  @ApiOperation(\"详情\")\n" +
                    "    @RequestMapping(path = \"details/{id}\", method = RequestMethod.POST)\n" +
                    "    public RestfulApiResponse<" + entity + "DetailsVo> details(@PathVariable(\"id\") String id) {\n" +
                    "        return RestfulApiResponse.success(\"success\", " + prefixLetterLower(entity) + "Service.details(id));\n" +
                    "    }\n");
        }

        sb.append("\n" +
                "    @ApiOperation(\"批量删除\")\n" +
                "    @RequestMapping(path = \"delete\", method = RequestMethod.POST)\n" +
                "    public RestfulApiResponse<Integer> delete(@RequestBody List<String> ids) {\n" +
                "        return RestfulApiResponse.success(\"success\", " + prefixLetterLower(entity) + "Service.batchDelete(ids));\n" +
                "    }\n" +
                "\n" +
                "}\n");
        return sb.toString();


    }

    /**
     * pageDto
     */
    public static String getPageDtoStr(String entity, String companyName, List<Parameters> parameterList) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".dto." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com." + companyName + ".framework.core.pojo.PaginationRequest;\n\n" +
                "import java.math.BigDecimal;\n" +
                "import java.util.Date;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public class " + entity + "PageDto extends PaginationRequest {\n");

        for (Parameters parameters : parameterList) {
            sb.append("    private String " + parameters.getKey() + ";\n");
        }

        sb.append("\n");
        for (Parameters parameters : parameterList) {
            sb.append("    public String get" + prefixLetterCap(parameters.getKey()) + "() {\n" +
                    "        return " + parameters.getKey() + ";\n" +
                    "    }\n" +
                    "\n" +
                    "    public void set" + prefixLetterCap(parameters.getKey()) + "(String " + parameters.getKey() + ") {\n" +
                    "        this." + parameters.getKey() + " = " + parameters.getKey() + ";\n" +
                    "    }\n");
        }
        sb.append("}\n");
        return sb.toString();
    }

    /**
     * pageVo
     */
    public static String getPageVoStr(String entity, String companyName, List<Parameters> parametersList) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();

        sb.append("package com." + companyName + ".vo." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import java.util.Date;\n" +
                "import java.util.List;\n" +
                "import java.math.BigDecimal;\n" +
                "import com.qhyt.vo.sys.TitleValueVo;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public class " + entity + "PageVo {\n\n");

        for (Parameters pageOrAddUpdateVoParameters : parametersList) {
            sb.append("    private " + pageOrAddUpdateVoParameters.getJavaType() + " " + pageOrAddUpdateVoParameters.getKey() + ";\n");
        }
/*

        sb.append("    private String insertUser;\n" +
                "    private Date insertTime;\n" +
                "    private String updateUser;\n" +
                "    private Date updateTime;\n");

        sb.append("    public String getId() {\n" +
                "        return id;\n" +
                "    }\n" +
                "\n" +
                "    public void setId(String id) {\n" +
                "        this.id = id;\n" +
                "    }\n" +
                "\n");
*/

        for (Parameters pageOrAddUpdateVoParameters : parametersList) {
            sb.append("    public " + pageOrAddUpdateVoParameters.getJavaType() + " get" + prefixLetterCap(pageOrAddUpdateVoParameters.getKey()) + "() {\n" +
                    "        return " + pageOrAddUpdateVoParameters.getKey() + ";\n" +
                    "    }\n" +
                    "\n" +
                    "    public void set" + prefixLetterCap(pageOrAddUpdateVoParameters.getKey()) + "(" + pageOrAddUpdateVoParameters.getJavaType() + " " + pageOrAddUpdateVoParameters.getKey() + ") {\n" +
                    "        this." + pageOrAddUpdateVoParameters.getKey() + " = " + pageOrAddUpdateVoParameters.getKey() + ";\n" +
                    "    }\n" +
                    "\n");
        }

     /*   sb.append("    public String getInsertUser() {\n" +
                "        return insertUser;\n" +
                "    }\n" +
                "\n" +
                "    public void setInsertUser(String insertUser) {\n" +
                "        this.insertUser = insertUser;\n" +
                "    }\n" +
                "\n" +
                "    public Date getInsertTime() {\n" +
                "        return insertTime;\n" +
                "    }\n" +
                "\n" +
                "    public void setInsertTime(Date insertTime) {\n" +
                "        this.insertTime = insertTime;\n" +
                "    }\n" +
                "\n" +
                "    public String getUpdateUser() {\n" +
                "        return updateUser;\n" +
                "    }\n" +
                "\n" +
                "    public void setUpdateUser(String updateUser) {\n" +
                "        this.updateUser = updateUser;\n" +
                "    }\n" +
                "\n" +
                "    public Date getUpdateTime() {\n" +
                "        return updateTime;\n" +
                "    }\n" +
                "\n" +
                "    public void setUpdateTime(Date updateTime) {\n" +
                "        this.updateTime = updateTime;\n" +
                "    }\n" +
                "}\n");*/
        return sb.toString();
    }


    /**
     * detailsVo
     */
    public static String getDetailsVoStr(String entity, String companyName, List<String> parameterClassNameList, List<Parameters>... parametersList) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".vo." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com.qhyt.vo.sys.TitleValueVo;\n" +
                "\n" +
                "import java.math.BigDecimal;\n" +
                "import java.util.Date;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public class " + prefixLetterCap(entity) + "DetailsVo {\n");
        // 表头信息
        for (Parameters header : parametersList[0]) {
            sb.append("    private " + header.getJavaType() + " " + header.getKey() + ";\n");
        }

        sb.append("\n");
        // 明细（内部类）
        for (int i = 0; i < parameterClassNameList.size(); i++) {
            String parameterClassName = parameterClassNameList.get(i);

            sb.append("    public static class " + parameterClassName + " {\n");
            for (Parameters detail : parametersList[i + 1]) {
                sb.append("        private " + detail.getJavaType() + " " + detail.getKey() + ";\n");
            }
            sb.append("\n");
            for (Parameters header : parametersList[i + 1]) {
                sb.append("        public " + header.getJavaType() + " get" + prefixLetterCap(header.getKey()) + "() {\n" +
                        "            return " + header.getKey() + ";\n" +
                        "        }\n" +
                        "\n" +
                        "        public void set" + prefixLetterCap(header.getKey()) + "(" + header.getJavaType() + " " + header.getKey() + ") {\n" +
                        "            this." + header.getKey() + " = " + header.getKey() + ";\n" +
                        "        }\n" +
                        "\n");
            }
            sb.append("    }\n\n");
        }

        sb.append("\n");
        // 表头get set
        for (Parameters header : parametersList[0]) {
            sb.append("    public " + header.getJavaType() + " get" + prefixLetterCap(header.getKey()) + "() {\n" +
                    "        return " + header.getKey() + ";\n" +
                    "    }\n" +
                    "\n" +
                    "    public void set" + prefixLetterCap(header.getKey()) + "(" + header.getJavaType() + " " + header.getKey() + ") {\n" +
                    "        this." + header.getKey() + " = " + header.getKey() + ";\n" +
                    "    }\n" +
                    "\n");
        }

        sb.append("}\n");
        return sb.toString();
    }

    /**
     * AddOrUpdateDto
     */
    public static String getAddOrUpdateDtoStr(String entity, String companyName, List<String> parameterClassNameList, List<Parameters>... parametersList) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".dto." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import com.qhyt.vo.sys.TitleValueVo;\n" +
                "\n" +
                "import java.math.BigDecimal;\n" +
                "import java.util.Date;\n" +
                "import java.util.List;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public class " + prefixLetterCap(entity) + "AddOrUpdateDto {\n");
        // 表头信息
        for (Parameters header : parametersList[0]) {
            String type = header.getType();
            if ("titleValue".equalsIgnoreCase(type)) {
                sb.append("    private String " + header.getKey() + ";\n");
            } else {
                sb.append("    private " + header.getJavaType() + " " + header.getKey() + ";\n");
            }
        }

        sb.append("\n");
        // 明细（内部类）
        for (int i = 0; i < parameterClassNameList.size(); i++) {
            String parameterClassName = parameterClassNameList.get(i);

            sb.append("    public static class " + parameterClassName + " {\n");
            for (Parameters detail : parametersList[i + 1]) {
                sb.append("        private " + detail.getJavaType() + " " + detail.getKey() + ";\n");
            }
            sb.append("\n");
            for (Parameters header : parametersList[i + 1]) {
                sb.append("        public " + header.getJavaType() + " get" + prefixLetterCap(header.getKey()) + "() {\n" +
                        "            return " + header.getKey() + ";\n" +
                        "        }\n" +
                        "\n" +
                        "        public void set" + prefixLetterCap(header.getKey()) + "(" + header.getJavaType() + " " + header.getKey() + ") {\n" +
                        "            this." + header.getKey() + " = " + header.getKey() + ";\n" +
                        "        }\n" +
                        "\n");
            }
            sb.append("    }\n\n");
        }

        sb.append("\n");
        // 表头get set
        for (Parameters header : parametersList[0]) {

            if ("titleValue".equalsIgnoreCase(header.getType())) {
                sb.append("    public String get" + prefixLetterCap(header.getKey()) + "() {\n" +
                        "        return " + header.getKey() + ";\n" +
                        "    }\n" +
                        "\n" +
                        "    public void set" + prefixLetterCap(header.getKey()) + "(String " + header.getKey() + ") {\n" +
                        "        this." + header.getKey() + " = " + header.getKey() + ";\n" +
                        "    }\n" +
                        "\n");
            } else {

            }
            sb.append("    public " + header.getJavaType() + " get" + prefixLetterCap(header.getKey()) + "() {\n" +
                    "        return " + header.getKey() + ";\n" +
                    "    }\n" +
                    "\n" +
                    "    public void set" + prefixLetterCap(header.getKey()) + "(" + header.getJavaType() + " " + header.getKey() + ") {\n" +
                    "        this." + header.getKey() + " = " + header.getKey() + ";\n" +
                    "    }\n" +
                    "\n");
        }

        sb.append("}\n");
        return sb.toString();
    }

    /**
     * AddOrUpdateDto
     */
    public static String getAddOrUpdateDtoStr(String entity, String companyName, List<Parameters> parameters) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".dto." + getPackagePrefix(entity) + ";\n" +
                "\n" +
                "import java.util.Date;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public class " + entity + "AddOrUpdateDto {\n\n");
        for (Parameters parameter : parameters) {

//            if ("BigDecimal".equals(parameter.getType())){
//                sb.append("    private ").append(parameter.getType()).append(" ").append(parameter.getKey()).append(" = new BigDecimal(0)").append(";\n");
//            }else{
            sb.append("   private " + parameter.getJavaType() + " " + parameter.getKey() + ";\n");
//            }
        }

        for (Parameters parameter : parameters) {
            sb.append("   public " + parameter.getJavaType() + " get" + prefixLetterCap(parameter.getKey()) + "() {\n" +
                    "        return " + parameter.getKey() + ";\n" +
                    "    }\n" +
                    "\n" +
                    "    public void set" + prefixLetterCap(parameter.getKey()) + "(" + parameter.getJavaType() + " " + parameter.getKey() + ") {\n" +
                    "        this." + parameter.getKey() + " = " + parameter.getKey() + ";\n" +
                    "    }\n");
        }


        sb.append("}\n");
        return sb.toString();
    }


    public static String getEnumStr(List<SysCodeSub> sysCodeSubList, String enumName, String companyName) {
        String dateStr = getDateStr();
        StringBuilder sb = new StringBuilder();
        sb.append("package com." + companyName + ".enums;\n" +
                "\n" +
                "import java.util.Date;\n" +
                "\n" +
                "/**\n" +
                " * @author jie\n" +
                " * @date " + dateStr + "\n" +
                " */\n" +
                "public enum " + prefixLetterCap(enumName) + "Enum {\n\n");

        for (SysCodeSub sysCodeSub : sysCodeSubList) {
            sb.append("    " + sysCodeSub.getSubCode().toUpperCase() + "(\"" + sysCodeSub.getSubCode() + "\",\"" + sysCodeSub.getNameCn() + "\"),\n");
        }

        sb.append("\t;\n");
        sb.append("\tprivate String code ;\n" +
                "    private String type;\n" +
                "\n" +
                "    " + prefixLetterCap(enumName) + "Enum(String code, String type){\n" +
                "        this.code = code;\n" +
                "        this.type = type;\n" +
                "    }\n" +
                "\n" +
                "    public String getCode() {\n" +
                "        return code;\n" +
                "    }\n" +
                "\n" +
                "    public void setCode(String code) {\n" +
                "        this.code = code;\n" +
                "    }\n" +
                "\n" +
                "    public String getType() {\n" +
                "        return type;\n" +
                "    }\n" +
                "\n" +
                "    public void setType(String type) {\n" +
                "        this.type = type;\n" +
                "    }\n");

        sb.append("}\n");
        return sb.toString();
    }

    // 生成checkAdd
    public static String getCheckAddStr(String entity, String field) {

        StringBuilder sb = new StringBuilder();
        sb.append("    public " + entity + " getBy" + prefixLetterCap(field) + "(String " + field + ") {\n" +
                "        Example example = new Example(" + entity + ".class);\n" +
                "        Example.Criteria criteria = example.createCriteria();\n" +
                "\n" +
                "        if (StringUtils.isNotEmpty(" + field + ")) {\n" +
                "            criteria.andEqualTo(\"" + field + "\", " + field + ");\n" +
                "        }\n" +
                "        List<" + entity + "> " + prefixLetterLower(entity) + "List = selectByExampleAndRowBounds(example, new RowBounds(), false);\n" +
                "\n" +
                "        if (CollectionUtils.notEmpty(" + prefixLetterLower(entity) + "List)) {\n" +
                "            return " + prefixLetterLower(entity) + "List.get(0);\n" +
                "        }\n" +
                "        return null;\n" +
                "    }\n\n");

        sb.append("    private void checkAdd(" + entity + "AddOrUpdateDto " + prefixLetterLower(entity) + "AddOrUpdateDto) {\n" +
                "        // 判断是否重复\n" +
                "        " + entity + " " + prefixLetterLower(entity) + " = " + prefixLetterLower(entity) + "Dao.getBy" + prefixLetterCap(field) + "(" + prefixLetterLower(entity) + "AddOrUpdateDto.get" + prefixLetterCap(field) + "());\n" +
                "        if (null != " + prefixLetterLower(entity) + ") {\n" +
                "            throw new RuntimeException(InternationalErrorCode." + humpToUnderline(field).toLowerCase() + "_EXIST.getInternationalMessage());\n" +
                "        }\n" +
                "\n" +
                "    }\n\n");

        sb.append("    " + humpToUnderline(field).toUpperCase() + "_EXIST(\"" + humpToUnderline(field).toLowerCase() + "_exist\"),\n\n");
        sb.append(prefixLetterCap(humpToBlank(field)) + " exist");
        return sb.toString();
    }

    /**
     * 拼接 service detail
     *
     * @param entity
     * @return
     */
    public static String getAppendServiceStr(String entity) {
        StringBuilder sb = new StringBuilder();
        sb.append("    " + entity + "DetailsVo details(String id);");
        return sb.toString();
    }

    /**
     * TestEntity → TEST_ENTITY
     */
    public static String getException(String entity) {
        return getPath(entity).toUpperCase();
    }

    /**
     * TestEntity → test_entity
     */
    public static String getPath(String entity) {
        StringBuilder sb = new StringBuilder();
        String realEntity = removePrefix(entity);
        int count = 0;
        for (int i = 0; i < realEntity.length(); i++) {
            char tempChr = realEntity.charAt(i);

            if (tempChr >= 'a' && tempChr <= 'z') {
                sb.append(tempChr);
            }

            if (tempChr >= 'A' && tempChr <= 'Z') {
                count++;
                tempChr += 32;
                if (count > 1) {
                    sb.append(UNDERLINE);
                }
                sb.append(tempChr);

            }
        }
        return sb.toString();
    }

    /**
     * TestEntity → test
     */
    public static String getPackagePrefix(String entity) {
        int index = 0;
        int count = 0;
        for (int i = 0; i < entity.length(); i++) {
            char tempChr = entity.charAt(i);
            if (tempChr >= 'A' && tempChr <= 'Z') {
                count++;
            }
            if (count > 1) {
                index = i;
                break;
            }
        }

        // 如果没有前缀，直接返回 entity
        if (count < 2) {
            return entity.substring(0, 1).toLowerCase() + entity.substring(1);
        }

        String upperPrefix = entity.substring(0, index);
        return upperPrefix.substring(0, 1).toLowerCase() + upperPrefix.substring(1);
    }

    /**
     * 去掉前缀
     * TestEntity → Entity
     */
    public static String removePrefix(String entity) {
        int index = 0;
        int count = 0;
        for (int i = 0; i < entity.length(); i++) {
            char tempChr = entity.charAt(i);
            if (tempChr >= 'A' && tempChr <= 'Z') {
                count++;
            }
            if (count > 1) {
                index = i;
                break;
            }
        }
        return entity.substring(index);
    }

    /**
     * TestEntity → testEntity
     */
    public static String prefixLetterLower(String str) {
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    /**
     * testEntity → TestEntity
     */
    public static String prefixLetterCap(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 下划线转驼峰
     */
    public static String underlineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 驼峰转换下划线
     */
    public static String humpToUnderline(String str) {
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * test_entity → test entity
     * 下划线转换空格
     */
    public static String underlineToBlank(String str) {
        return str.replaceAll("_", " ");
    }

    /**
     * 驼峰线转换空格
     */
    public static String humpToBlank(String str) {
        return humpToUnderline(str).replaceAll("_", " ");
    }

    /**
     * 向文件后追加字符串（目前在最后的一个 '}' 中追加）
     *
     * @param appendStr 拼接的字符串
     * @param file      文件
     * @throws Exception
     */
    public static void appendStr(String appendStr, File file) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(file));

        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line).append("\n");
        }

        FileOutputStream fos = new FileOutputStream(file);
        String codeStr = sb.toString();
        int lastKuoHao = codeStr.lastIndexOf("}");

        if (lastKuoHao != -1) {
            appendStr = appendStr + "\n}";
            codeStr = codeStr.substring(0, lastKuoHao) + appendStr;

        }

        fos.write(codeStr.getBytes());
        fos.close();
        br.close();
    }


}
